在程式與資料庫的交互中,除了事務的概念外,還有一個另一個同樣重要的概念就是鎖(Lock)
什麼是鎖?
鎖是用於一種處理高併發(Concurrent)訪問共用資源的一種機制,主要目的是在多執行緒 (Thread) 中同時訪問某一個資源時,防止資料發生不一致或衝突。鎖的機制用於確保在某個時段只會有一個執行緒可以存取特定的資源,避免發生競爭關係(Race Condition)。
鎖的概念被廣泛應用在計算機科學的不同領域,例如作業系統、應用程式、資料庫等。
本篇文章將以 Spring Boot 為應用範例, MSSQL 為資料庫範例,解釋鎖在這兩個不同領域的應用。
Spring Boot 中的鎖
在Spring Boot 或 Java 的應用中,鎖通常用於處理多執行緒的併發問題,用於確保多執行緒對於共用資源的存取與一致性。
舉個計數器的例子如下:
public class SyncProblemExample {
private int counter = 0;
public void increment() {
counter++;
}
public int getCounter() {
return counter;
}
public static void main(String[] args) throws InterruptedException {
SyncProblemExample example = new SyncProblemExample();
Thread thread1 = new Thread(() -> {
for (int i = 0; i < 1000; i++) {
example.increment();
}
});
Thread thread2 = new Thread(() -> {
for (int i = 0; i < 1000; i++) {
example.increment();
}
});
thread1.start();
thread2.start();
thread1.join();
thread2.join();
System.out.println("Final Counter Value: " + example.getCounter());
}
}
假設今天有兩個執行緒會同時透過 increment 這個方法累加 counter 的值,因為兩個執行緒是併發執行的,在沒有使用鎖機制的情況下,可能會造成 counter 最後累加的結果不是 2000 (理論上,兩個執行緒各累加1000最後的結果應為2000),也就是發生所謂的同步問題。
在上述的案例中,如果我們想要避免引發同步問題,就需要在 increment方法上加上鎖的機制,每次只接受一個執行緒將 counter 的值進行累加。
MSSQL中的鎖
在資料庫中,鎖只要應用於控制併發事務的訪問,用於確保多事務在同時操作資料庫資料的完整性和一致性。
MSSQL中的鎖可以根據需求加在不同的層級上,可以針對特定資料行進行鎖(Row-Level Locking),也能夠針對整個表加鎖(Table-Level Locking),也可以說是上鎖的”範圍”,可以由特定資料行到整張資料表。
另外,資料庫會根據事務隔離層級來控制多事務訪問時的鎖定行為。假設在 Read Committed 層級下,多個事務可以同時持有共享鎖來讀取資料,但事務要進行寫入操作時,只會有一個事務可以修改資料,可以修該資料的事務將會持有排它鎖,避免其他事務進行資料寫入的操作。
其實我覺得自己目前對於鎖的概念還在一個很淺很淺的階段,但我知道它在高流量、高併發的應用場景,尤其是與資料庫進行互動時的重要性。因此,我想先分享自己目前的學習心得,未來隨著實際應用經驗的積累,我會再進一步分享。